﻿using Coolzon.Common;
using Coolzon.UI.Core.Animation;
using Coolzon.UI.Core.Runtime;
using Coolzon.UI.Core.Runtime.Script;
using CPPEI.Coolzon.UI.Data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using RT = Coolzon.Metadata.Runtime;

namespace Coolzon.UI.Core
{
    /// <summary>
    /// 场景更新事件
    /// </summary>
    /// <param name="scene"></param>
    public delegate void SceneUpdated(Scene scene);

    /// <summary>
    /// 场景打开事件
    /// </summary>
    /// <param name="scene"></param>
    public delegate void SceneOpened(Scene scene);

    /// <summary>
    /// 缩放
    /// </summary>
    /// <param name="oldFactor"></param>
    /// <param name="newFactor"></param>
    public delegate void ZoomEventHandler(double oldFactor, double newFactor);

    /// <summary>
    /// 组件框架可以承载组件
    /// 每一个Frame具有一个PartContext
    /// </summary>
    public sealed partial class Frame : ContentControl, IScriptHost
    {
        static Frame()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Frame), new FrameworkPropertyMetadata(typeof(Frame)));
        }

        private Runtime.Script.FrameScriptObject _scriptObject;

        /// <summary>
        /// 组件运行的上下文
        /// </summary>
        public PartContext PartContext { get; private set; }

        /// <summary>
        /// 组件表
        /// </summary>
        public System.Collections.Hashtable ComponentTable;

        public double HorizontalOffset
        {
            get
            {
                return (double)this.GetValue(HorizontalOffsetProperty);
            }
            set
            {
                this.SetValue(HorizontalOffsetProperty, value);
            }
        }

        public double VerticalOffset
        {
            get
            {
                return (double)this.GetValue(VerticalOffsetProperty);
            }
            set
            {
                this.SetValue(VerticalOffsetProperty, value);
            }
        }
        #region dependency properties

        public static readonly DependencyProperty HorizontalOffsetProperty =
            DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(Frame),
            new PropertyMetadata(Double.MinValue, new PropertyChangedCallback(Frame.OnHorizontalOffsetPropertyChanged)));

        public static readonly DependencyProperty VerticalOffsetProperty =
            DependencyProperty.Register("VerticalOffset", typeof(double), typeof(Frame),
            new PropertyMetadata(Double.MinValue, new PropertyChangedCallback(Frame.OnVerticalOffsetPropertyChanged)));

        #endregion

        #region scroll
        public Size FrameSize { get; private set; }
        public Size ContentSize { get; private set; }
        /// <summary>
        /// 是否已经更新过显示模式了，只有更新过显示模式之后，大小变动事件才会激活重新更新显示模式
        /// </summary>
        private bool _hasUpdateDisplayMode = false;
        #endregion

        /// <summary>
        /// 需要滚动的水平偏移值，对于场景的循环显示
        /// </summary>
        private double _hLoopOffset;

        public Locator Locator { get; private set; }
        internal Canvas _container;
        /// <summary>
        /// 当前显示的组件
        /// </summary>
        private Scene _currentPart;
        /// <summary>
        /// 上一个场景
        /// </summary>
        private Scene _lastPart;
        /// <summary>
        /// 本次要显示的场景
        /// </summary>
        private Scene _enteringPart;
        /// <summary>
        /// 进入的场景的动画
        /// </summary>
        private SwitchAnimation _enteringAnimation;

        private Scene _leaveingPart;
        private Storyboard _switchStoryboard;

        #region animation

        ScaleTransform _scaleIn;
        ScaleTransform _scaleOut;
        DoubleAnimation _aniInOpacity;
        DoubleAnimation _animationIn;
        DoubleAnimation _animationInY;
        DoubleAnimation _aniOutOpacity;
        DoubleAnimation _animationOut;
        #endregion

        ///// <summary>
        ///// 记录区域实际的偏移值，用于定位到区域
        ///// </summary>
        //Dictionary<Part, Point> _areaActualOffset;

        //internal ScrollViewer _scrollViewer;

        /// <summary>
        /// 在运行时，是不允许滚动的，设计时允许滚动
        /// </summary>
        private bool _isCanScroll = false;
        /// <summary>
        /// 是否可以滚动
        /// </summary>
        [Obsolete("remove this property", true)]
        public bool IsCanScroll
        {
            get
            {
                return _isCanScroll;
            }
            set
            {
                //if (_isCanScroll != value)
                //{
                //    if (value)
                //    {
                //        this.Content = _scrollViewer;
                //        //this._scrollViewer.Content = _container;
                //        this._scrollViewer.Children.Add(_container);
                //    }
                //    else
                //    {
                //        //this._scrollViewer.Content = null;
                //        this._scrollViewer.Children.Clear();
                //        this.Content = _container;
                //    }
                //}
                _isCanScroll = value;
            }
        }

        private bool _isAutoSize = false;

        /// <summary>
        /// 移动区域时的动画
        /// </summary>
        private Storyboard _moveAreaStoryboard;
        private string _moveSourceArea;
        private string _moveDestArea;

        [Obsolete("请使用CurrentScene来获取当前场景")]
        public Scene CurrentPart
        {
            get
            {
                return _currentPart;
            }
        }

        /// <summary>
        /// 切换动画
        /// </summary>
        private SwitchAnimation _switchAnimation;
        private SwitchType _switchType;

        private Storyboard _scrollStoryBoard;

        public event SceneUpdated OnSceneUpdated;

        /// <summary>
        /// 场景打开事件
        /// </summary>
        public event SceneOpened OnSceneOpened;

        /// <summary>
        /// 移动激光笔的动画
        /// </summary>
        private Storyboard _moveLaserPointerStoryboard;
        private DoubleAnimation _moveLaserPointerAnimationLeft;
        private DoubleAnimation _moveLaserPointerAnimationTop;

        /// <summary>
        /// 移动放大镜的动画
        /// </summary>
        private Storyboard _moveMagnifyStoryboard;
        private DoubleAnimation _moveMagnifyAnimationLeft;
        private DoubleAnimation _moveMagnifyAnimationTop;

        /// <summary>
        /// 放大倍数
        /// </summary>
        private double _magnifyRate = 1.5d;

        /// <summary>
        /// 缩放事件
        /// </summary>
        public event ZoomEventHandler OnZooming;

        public Frame()
        {
            //IsCanScroll = false;
            _isCanScroll = false;
            _container = new Canvas();
            _container.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            _container.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
            //_container.Background = new SolidColorBrush(Colors.White);


            //_scrollViewer = new ScrollViewer();
            //_scrollViewer.Background = new SolidColorBrush(Colors.White);
            //_scrollViewer.Padding = new Thickness(0);
            //_scrollViewer.Margin = new Thickness(0);
            //_scrollViewer.BorderThickness = new Thickness(0);
            //_scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
            //_scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;

            //_scrollViewer.PanningMode = PanningMode.Both;
            //_scrollViewer.PanningMode = PanningMode.Both;
            //_scrollViewer.CanContentScroll = true;
            //_scrollViewer.ScrollChanged += _scrollViewer_ScrollChanged;

            //_scrollViewer.Content = _container;
            //this.Content = _scrollViewer;

            this.Content = _container;

            //this.Background = new SolidColorBrush(Colors.Green);
            //this._container.Background = new SolidColorBrush(Colors.Yellow);

            this.ZoomFactor = 1.0d;

            Locator = new Locator(this);
        }

        void _scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            ValidateCurrentPartVisibleRange();

            if (_currentPart != null)
            {
                if (OnSceneUpdated != null)
                {
                    OnSceneUpdated(_currentPart as Scene);
                }
            }
        }

        /// <summary>
        /// 校验实际的显示区域，用于帮助activex组件裁剪
        /// </summary>
        public void ValidateCurrentPartVisibleRange()
        {
            //if (_currentPart != null)
            //{
            //    Point ltInContainer = _scrollViewer.PointToScreen(new Point(0, 0));
            //    Point rtInContainer = _scrollViewer.PointToScreen(new Point(_scrollViewer.ActualWidth, _scrollViewer.ActualHeight));
            //    _currentPart.VisibleRegionChange(ltInContainer, rtInContainer);
            //}
        }

        /// <summary>
        /// frame的大小和显示的组件的大小一样大
        /// </summary>
        public void SetAutoSize()
        {
            _isAutoSize = true;
            if (this._currentPart != null)
            {
                this.Width = this._currentPart.Width;
                this.Height = this._currentPart.Height;
            }
        }

        /// <summary>
        /// 删除框架里的组件
        /// </summary>
        /// <returns></returns>
        public Widget RemoveCurrentPart()
        {
            //if (_currentPart != null)
            //{
            //    this._container.Children.Remove(_currentPart);
            //}
            
            //Part part = _currentPart;
            //_currentPart = null;
            //return part;
            return null;
        }

        /// <summary>
        /// 获取摄像机的位置（左上角)
        /// </summary>
        /// <returns></returns>
        public Point GetCameraPos()
        {
            return new Point(this.HorizontalOffset, this.VerticalOffset);
        }

        ///// <summary>
        ///// 保存场景中区域的相对位置
        ///// </summary>
        //public void StoreAreaActualOffset()
        //{
        //    // 保存区域的相对位置
        //    if (_areaActualOffset == null)
        //    {
        //        Scene Scene = (_currentPart as Scene);
        //        _areaActualOffset = new Dictionary<Part, Point>();
        //        for (int index = 0; index < Scene.SceneMatadata.Areas.Count; index++)
        //        {
        //            Coolzon.Metadata.Area areaMetadata = Scene.SceneMatadata.Areas[index];
        //            UI.AreaPart areaPart = Scene.GetChildPart(areaMetadata.Name, false) as UI.AreaPart;
        //            _areaActualOffset.Add(areaPart, areaPart.PointToScreen(new Point(0, 0)));
        //        }
        //    }
        //}

        ///// <summary>
        ///// 评级切换动画
        ///// </summary>
        ///// <param name="part"></param>
        //public void ShowPartWithAnimationSameLevel(Part part)
        //{
        //    if (!this._container.Children.Contains(part))
        //    {
        //        this._container.Children.Add(part);
        //    }
        //    _enteringPart = part;
        //    SwitchAnimationMode = FrameSwitchAnimationMode.FrontToBack;
        //}

        /// <summary>
        /// 关闭当前场景，返回上一个场景
        /// </summary>
        //public void Back()
        //{
        //    if (_lastPart != null)
        //    {
        //        this.SetPartVisible(_lastPart, true);
        //        if (_leaveingPart != null)
        //        {
        //            System.Windows.Controls.Panel.SetZIndex(_leaveingPart, 0);
        //        }
        //    }

        //    if (_currentPart != null)
        //    {
        //        _leaveingPart = _currentPart;
        //        this.SetPartVisible(_leaveingPart, true);
        //        System.Windows.Controls.Panel.SetZIndex(_leaveingPart, 1);

        //        Logger.WarningToTag("UI", string.Format("Frame animation Finish enteringPart:{0} type:{1}, 关闭当前场景，返回上一个场景", _switchAnimation.Part.Name, _switchAnimation.Part.GetType().Name));

        //        _switchAnimation.Prepare(SwitchType.Out, this, _leaveingPart);
        //        _switchAnimation.Begin();
        //    }
        //    _currentPart = _lastPart;
        //}

        private PartContext CreatePartContext(RT.Solution solutionMetadata, RT.Scene sceneMetadata)
        {
            PartContext = new PartContext(new Runtime.Script.ScriptEngine(string.Format("SE:{0}", sceneMetadata.Name)),
                solutionMetadata,
                sceneMetadata);
            // 加载场景的脚本文件
            // 添加窗口对象，用于交互
            PartContext.ScriptEngine.AddObject("frame", this.GetScriptObject());

            if (sceneMetadata != null && sceneMetadata.Scripts != null)
            {
                for (int index = 0; index < sceneMetadata.Scripts.Count; index++)
                {
                    if (!string.IsNullOrEmpty(sceneMetadata.Scripts[index].Source))
                    {
                        string scriptFilePath = SolutionResouseManager.GetAbsoluteFilePath(sceneMetadata.Scripts[index].Source);
                        PartContext.ScriptEngine.AddFile(scriptFilePath);
                    }
                    else if (!string.IsNullOrEmpty(sceneMetadata.Scripts[index].Content))
                    {
                        PartContext.ScriptEngine.AddCode(sceneMetadata.Scripts[index].Content);
                    }
                }
            }
            return PartContext;
        }

        /// <summary>
        /// 初始化Frame，
        /// 主要是要初始化Frame里的PartContext
        /// </summary>
        /// <param name="solutionMetadata"></param>
        public void Init(RT.Solution solutionMetadata)
        {
        }

        //public void SetViewState(ViewState viewState)
        //{
        //    if (_currentPart != null)
        //    {
        //        _currentPart.LoadViewState(viewState);
        //    }
        //    else if (_enteringPart != null)
        //    {
        //        _enteringPart.LoadViewState(viewState);
        //    }
        //}

        [Obsolete("bug:应该不需要传递参数")]
        public void Active(RT.Scene sceneMetadata, bool isShowActiveXPart, OpenSceneArgs args)
        {
        }

        #region override IComponent methods
        public object GetScriptObject()
        {
            if(_scriptObject == null)
            {
                _scriptObject = new FrameScriptObject(this);
            }
            return _scriptObject;
        }
        #endregion

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            // 大小改变的时候，调整显示组件的缩放大小
            this.Locator.Relocate();

            base.OnRenderSizeChanged(sizeInfo);
        }

        #region dependency method

        private static void OnHorizontalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Frame frame = d as Frame;
            //frame._scrollViewer.ScrollToHorizontalOffset((double)e.NewValue);
            //for (int index = 0; index < frame._scrollViewer.Children.Count; index++)
            //{
            //    Canvas.SetLeft(frame._scrollViewer.Children[index], -(double)e.NewValue);
            //}
        }

        private static void OnVerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Frame frame = d as Frame;
            //frame._scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
            //for (int index = 0; index < frame._scrollViewer.Children.Count; index++)
            //{
            //    Canvas.SetTop(frame._scrollViewer.Children[index], -(double)e.NewValue);
            //}
        }

        #endregion

        #region view state
        //public void LoadViewState(ViewState viewState)
        //{
        //    Scene scene = this.CurrentPart as Scene;
        //    if (scene != null)
        //    {
        //        scene.LoadViewState(viewState);
        //    }
        //}

        //public void SaveViewState(ViewState viewState)
        //{
        //    Scene scene = this.CurrentPart as Scene;
        //    if (scene != null)
        //    {
        //        scene.SaveViewState(viewState);
        //    }
        //}
        #endregion

        /// <summary>
        /// 获取显示的场景的大小
        /// </summary>
        /// <returns></returns>
        public Size GetSceneSize()
        {
            if (this._currentPart != null)
            {
                return new Size(_currentPart.Width, _currentPart.Height);
            }
            return new Size(0, 0);
        }
    }
}
